package hehe.validation;

import hehe.validation.annotation.ValidAnnotation;
import hehe.validation.base.Rule;
import hehe.validation.base.Verify;
import hehe.validation.util.ValidatorUtil;
import hehe.validation.validator.Validator;
import hehe.validation.validator.ValidAlias;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 验证工具类
 *<B>说明：</B>
 *<pre>
 * 略 类详细描述
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
public class Validation
{

    static {
        // 开始扫描Validator 验证类,识别ValidatorAlias 注解的信息,解析Validator别名,对应注解的关系
        ValidAnnotation.scanValidator(Validator.getPackageName());
        // 扫描Validator注解
        ValidAnnotation.scanAnnotation(ValidAnnotation.getPackageName());
    }

    /**
     * 错误消息列表
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected List<Error> errors = new ArrayList<>();

    /**
     * 验证规则
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    List<Rule> rules = new ArrayList<>();

    public static void addValidatorAlias(String alias,Class validator)
    {
        ValidAlias.putValidatorAlias(alias,validator);
    }

    public static Class getValidatorByAlias(String alias)
    {
        return ValidAlias.getValidator(alias);
    }

    /**
     * 设置验证规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Rule on(String attr,String validator)
    {
        Rule rule = new Rule(attr,validator);
        rule.setValidation(this);
        this.rules.add(rule);

        return rule;
    }

    /**
     * 设置验证规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public Rule on(String attr,Verify... verifys)
    {
        Rule rule = new Rule(attr,verifys);
        rule.setValidation(this);
        this.rules.add(rule);

        return rule;
    }

    /**
     * 验证入口
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public boolean validate(Map<String,Object> attrs)
    {
        // 获取验证规则
        List<Rule> rules = this.buildActiveRule(null,null);

        return this.valid(attrs,true,rules);
    }

    /**
     * 验证对象入口
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     * @param target 验证属性值
     */
    public boolean validate(Object target)
    {
        return this.validate(target,true,null);
    }

    /**
     * 验证对象入口
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     * @param target 验证属性值
     * @param clearErrors 是否清空之前的错误消息
     * @param scenes 场景列表               　
     */
    public boolean validate(Object target,boolean clearErrors,String... scenes)
    {
        // 读取对象属性对象
        Map<String,Object> attrs = ValidatorUtil.getAttrs(target);

        // 属性为空,不验证
        if (attrs.size() == 0) {
            return true;
        }

        // 获取验证规则
        List<Rule> rules = this.buildActiveRule(target.getClass(),scenes);
        return this.valid(attrs,clearErrors,rules);
    }

    /**
     * 验证规则
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     * @param attrs 验证属性值
     * @param clearErrors 是否清空之前的错误消息
     */
    private boolean valid (Map<String,Object> attrs,boolean clearErrors,List<Rule> rules)
    {
        if (clearErrors == true) {
            this.clearErrors();
        }

        // 验证是否有规则,无验证规则，则直接返回
        if (rules.size() == 0) {
            return true;
        }

        boolean validateResult = true;
        boolean result;
        // 遍历验证
        for (Rule rule:rules) {
            rule.setValidation(this);
            result = rule.validateRule(attrs);
            if (result == false) {
                validateResult = false;
                // 是否继续验证
                if (!rule.goOn()) {
                    break;
                }
            }
        }

        return validateResult;
    }

    /**
     * 构建可用激活的验证规则
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param scenes 场景列表
     */
    private List<Rule> buildActiveRule(Class targetclazz,String[] scenes)
    {
        List<Rule> rules = new ArrayList<>();

        // 注解验证规则
        if (targetclazz != null) {
            List<Rule> annRules = ValidAnnotation.getRules(targetclazz);
            if (annRules != null) {
                for (Rule rule:annRules) {
                    if (rule.isActive(scenes)) {
                        rules.add(rule);
                    }
                }
            }
        }

        // 设置验证规则
        for (Rule rule:this.rules) {
            if (rule.isActive(scenes)) {
                rules.add(rule);
            }
        }

        return rules;
    }

    /**
     * 添加错误消息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void addError(Error error)
    {
        this.errors.add(error);
    }

    /**
     * 是否有错误
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public boolean hasError()
    {
        if (this.errors.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取首个错误消息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public String getFirstError()
    {
        if (!this.hasError()) {
            return "";
        }

        return this.errors.get(0).getMessage();
    }

    /**
     * 清空错误消息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    public void clearErrors()
    {
        this.errors.clear();
    }

    /**
     * 生产validator 类名
     *<B>说明：</B>
     *<pre>
     * 略
     *</pre>
     */
    public Class buildValidator(String validatorName)
    {
        if (ValidAlias.getValidator(validatorName) != null) {
            return ValidAlias.getValidator(validatorName);
        }

        try {
            if (validatorName.indexOf(".") == -1) {
                validatorName = Validator.getPackageName() + "." + ValidatorUtil.upperCase(validatorName) + "Validator";
            }

            Class validatorClazz = Class.forName(validatorName);

            return validatorClazz;
        } catch (ClassNotFoundException ex) {
            return null;
        } catch (Exception ex) {
            return null;
        }
    }

}
